#ifndef BCMC_CNC_BASE_CNC_KERNEL_H
#define BCMC_CNC_BASE_CNC_KERNEL_H

#include <bcm/bcm.h>
// provided interfaces
#include <bcmi_taskctl.h>     // base/kernel
#include <bcmi_kernelsetup.h> // base/kernel

namespace cnc {

	namespace base {

		struct BCMC_CNCKernel :
			public bcm::Identifier<bcm::Component>,
			public bcm::Identifier<BCMI_KernelSetup>,
			public bcm::Identifier<BCMI_TaskControl>
		{
			KernelSetup *krnlSetup_;
			CooperativeTask *coopTask_;
		protected:
			BCMC_CNCKernel();
		protected: // bcm::Component
			virtual bcm::IdentifierData *getProvidedInterfaceTable()
			{
				static bcm::IdentifierData idData[] = {
					{ "taskctl", "Task Control" },
					{ "krnlsetup", "Kernel Setup" },
					{ 0, 0 }
				};
				return idData;
			}
			virtual bcm::IdentifierData *getRequiredInterfaceTable()
			{
				static bcm::IdentifierData idData[] = {
					{ "taskctl", "Task Control (for background tasks)" },
					{ 0, 0 }
				};
				return idData;
			}
			virtual bcm::Interface *getInterface(const char *id)
			{
				if (std::string("krnlsetup") == id)
					return static_cast<BCMI_KernelSetup *>(this);
				else if (std::string("taskctl") == id)
					return static_cast<BCMI_TaskControl *>(this);
				return 0;
			}
			virtual bool setInterface(bcm::Interface *iface)
			{
				if (iface == 0)
					return false;
				if (std::string("taskctl") == iface->getID()) {
					BCMI_TaskControl *tc = dynamic_cast<BCMI_TaskControl *>(iface);
					if (tc == 0)
						return false;
					addTask(tc);
				} else
					return false;
				return true;
			}
		private: // Kernel Setup
			virtual void addTask(CooperativeTask *backgroundTask);
			virtual void addMode(OperationModeID modeID, CooperativeMode *operationMode);
			virtual void selectMode(OperationModeID modeID);
			virtual OperationModeID getMode();
		private: // Task Control
			virtual bool start();
			virtual bool execute();
			virtual bool stop();
		public:
			static BCMC_CNCKernel &instance()
			{
				static BCMC_CNCKernel object;
				return object;
			}
		};

	} // namespace base

} // namespace cnc

#endif
